#region Imported Namespaces
using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Web;
using System.Text;
using System.Web.SessionState;
using System.Web.Security;
using System.Security.Principal;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Diagnostics;

using PHSRAG.Insight21.Policy;
using PHSRAG.Insight21.CDS;
using PHSRAG.Utility;
using PHSRAG.Insight21.Context;
using PHSRAG.Insight21.SearchContext;
using ER = PHSRAG.Utility.ExceptionReport;

#endregion

namespace PHSRAG.Insight21
{
    /// <summary>
    /// The Global class provides the launch-pad for the application and its myriad of events.
    /// </summary>
    public class Global : HttpApplication
    {
        #region Constants
        private const string DisplayFriendErrorKey = "displayFriendlyError_F88BA85A-7F31-40c8-8D9A-92E632E8C021";
        public const string DisplayStackTraceKey = "displayStackTrace_F88BA85A-7F31-40c8-8D9A-92E632E8C021";
        public const char GroupDelimiter = '|';
        private const string TrackActivityKey = "trackActivity_F88BA85A-7F31-40c8-8D9A-92E632E8C021";
        #endregion

        #region Public Methods
        /// <summary>
        /// The default constructor for the Global class. Initializes all components.
        /// </summary>
        public Global()
        {
            InitializeComponent();
        }
        #endregion

        #region Event Handlers
        /// <summary>
        /// Event raised when the first request hits the server
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_Start(Object sender, EventArgs e)
        {
            //Ahmad Added for debugging
            log4net.Config.XmlConfigurator.Configure();

            Application[DisplayFriendErrorKey] = Settings.GetKeyValue("DisplayErrors.Friendly", true);
            Application[DisplayStackTraceKey] = Settings.GetKeyValue("DisplayErrors.ShowStackTrace", false);
            Application[TrackActivityKey] = Settings.GetKeyValue("TrackActivity", true);

            Policy.ICachePolicy cachePolicy = null;

            // Load the cache policy class to be used for page objects.
            if (Application[Policy.Names.ApplicationCachePolicyKey] == null)
            {
                string assemblyName = Settings.GetKeyValue("ApplicationCachePolicyProvider.Assembly", null);
                string className = Settings.GetKeyValue("ApplicationCachePolicyProvider.Class", null);

                cachePolicy = (Policy.ICachePolicy)InstanceCreator.Create(assemblyName, className, Application);
                if (cachePolicy == null)
                    cachePolicy = new Policy.NullCachePolicy();
                Application[Policy.Names.ApplicationCachePolicyKey] = cachePolicy;
            }

            //Load RefCodes data
            if (cachePolicy.GetCachedObject(CDS.RefCodes.CacheKey) == null)
            {
                CDS.RefCodes refCodes = new PHSRAG.Insight21.CDS.RefCodes(cachePolicy);
                refCodes.Load(DataAccess.ConnectionString, null);
                cachePolicy.Cache(CDS.RefCodes.CacheKey, refCodes);
            }

            Application[InsightUtilities.Constants.HumansRolesKey] =
                Humans.StudyStaff.GetHumansStudyRoles(DataAccess.ConnectionString);

            Application[InsightUtilities.Constants.AnimalsRolesKey] =
                Humans.StudyStaff.GetAnimalsStudyRoles(DataAccess.ConnectionString);

            Application[InsightUtilities.Constants.FeedType.Cachekey] = RefCode.GetLastFeedDates();

        }

        /// <summary>
        /// Event raised when any new user hits the Web site.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Session_Start(Object sender, EventArgs e)
        {
            // Load the cache policy class to be used for business objects.
            if (Session[Policy.Names.CachePolicyKey] == null)
            {
                string assemblyName = Settings.GetKeyValue("CachePolicyProvider.Assembly", null);
                string className = Settings.GetKeyValue("CachePolicyProvider.Class", null);

                Policy.ICachePolicy cachePolicy = (Policy.ICachePolicy)InstanceCreator.Create(assemblyName, className, Session);
                if (cachePolicy == null)
                    cachePolicy = new Policy.NullCachePolicy();
                Session[Policy.Names.CachePolicyKey] = cachePolicy;

                cachePolicy.Cache(InsightUtilities.Constants.HumansRolesKey,
                    Application[InsightUtilities.Constants.HumansRolesKey]);

                cachePolicy.Cache(InsightUtilities.Constants.AnimalsRolesKey,
                    Application[InsightUtilities.Constants.AnimalsRolesKey]);
            }

            // Load the cache policy class to be used for page objects.
            if (Session[Policy.Names.PageCachePolicyKey] == null)
            {
                string assemblyName = Settings.GetKeyValue("PageCachePolicyProvider.Assembly", null);
                string className = Settings.GetKeyValue("PageCachePolicyProvider.Class", null);

                Policy.ICachePolicy cachePolicy = (Policy.ICachePolicy)InstanceCreator.Create(assemblyName, className, Session);
                if (cachePolicy == null)
                {
                    cachePolicy = new Policy.NullCachePolicy();
                }
                Session[Policy.Names.PageCachePolicyKey] = cachePolicy;
                string referringPage = Path.GetFileName(Request.Path).ToLower();

                //*******************Changes for Single Sign On*********************************
                if (Settings.GetKeyValue("SingleSignOnEnabled", false))
                {
                    /*Code to check for session expiration and if expired redirection to the logout.asp page of RSA*/
                    try
                    {
                        HttpContext context = HttpContext.Current;
                        HttpCookieCollection cookies = context.Request.Cookies;
                        if (cookies["starttime"] == null || referringPage != "login.asp")
                        {
                            HttpCookie cookie = new HttpCookie("starttime", DateTime.Now.ToString());
                            cookie.Path = "/";
                            context.Response.Cookies.Add(cookie);

                            string queryCookie = string.Empty;
                            string businessUserCookie = string.Empty;
                            string businessUser = string.Empty;

                            /*User who is logging into the application or trying to impersonate another user*/
                            string userName = Request.Headers["ct-remote-user"];

                            /*This section is used to get the user to impersonate
                             and relates to the BusinessUser textbox on the login.asp page*/
                            if (Request.Cookies["sys"] != null)
                            {
                                queryCookie = Convert.ToString(Request.Cookies["sys"].Value);
                                businessUser = Request.Headers["businessUser"];
                                if (Request.Cookies["businessUser"] != null)
                                {
                                    businessUserCookie = Request.Cookies["businessUser"].Value;
                                }
                            }

                            if (queryCookie.ToLower() == "sysadmin" && businessUserCookie != string.Empty)
                            {
                                Login.LoadSysUserContext(userName, businessUserCookie, (Policy.ICachePolicy)Session[Policy.Names.CachePolicyKey]);
                            }
                            else
                            {
                                Login.LoadUserContext(userName, (Policy.ICachePolicy)Session[Policy.Names.CachePolicyKey]);
                            }

                            //if (Utility.Settings.GetKeyValue("redirectionPage", "").Contains(referringPage.ToLower()) && Utility.Settings.GetKeyValue("redirectToPageInUrl", false))
                            if (Utility.Settings.GetKeyValue("redirectToPageInUrl", false))
                            {
                                Response.Redirect(Request.RawUrl);
                            }
                            else
                            {
                                //Go to the home page
                                Response.Redirect(Utility.Settings.GetKeyValue("Header.HomeURL", ""));
                            }
                        }
                        else
                        {
                            Server.Transfer(Utility.Settings.GetKeyValue("Header.Logout", "") + "?message=" + "Your session has timed out due to an extended period of inactivity.", true);
                        }

                        /*sessione xpiration changes end*/
                    }
                    catch (Exception ex)
                    {
                        Response.Redirect(Utility.Settings.GetKeyValue("Header.Logout", "") + "?message=" + ex.Message);
                    }

                }
                else//Original Implementation
                {

                    if ((referringPage != "login.aspx") && (referringPage != "reportmanagement.aspx") && (referringPage != "ssoaccessrouter.aspx"))
                    {
                        // We are in session_start due to a previous session timeout
                        // cache the fact that it is a session timeout restart
                        Hashtable outgoingData = new Hashtable();
                        outgoingData.Add(Keys.SessionHasTimedOutKey, "true");
                        cachePolicy.Cache(Keys.IncomingDataKey, outgoingData);

                        Response.Redirect("~/Login.aspx");
                    }
                }
            }

        }

        /// <summary>
        /// This Event is mainly used to support the reporting tool(under Report module)
        /// Reason:
        ///	The tool tries to get all the required values from the System.Web.HttpContext that will  
        ///	created on each request and destroyed after the response.Also the control requires these values 
        ///	even before the page is initialized,Hence the required values cannot be assigned on the page.
        /// Due to the above fact,The parameters for the report(in the httpContext) can be set on either Application_BeginRequest 
        /// or Application_PreRequesthandlerExecute
        /// 
        /// Why httpContext values were not set on the Application_BeginRequest?
        ///  This place is ideal as long as the session is not accessed(Session state is unavailable at this point).
        ///  As the user context uses the cachepolicy which in turn relies on the Session state, the parameters can't be set in Application_BeginRequest. 
        /// </summary>
        /// <param name="sender">Source of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void Application_PreRequesthandlerExecute(Object sender, EventArgs e)
        {
            try
            {
                Policy.ICachePolicy cachePolicy = (Policy.ICachePolicy)Session[Policy.Names.PageCachePolicyKey];
                if (cachePolicy != null)
                {
                    UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                    if (userContext != null)
                    {
                        System.Web.HttpContext.Current.Items["PersonId"] = userContext.PersonId;
                        System.Web.HttpContext.Current.Items["DomainUserId"] = userContext.DomainUserId;
                        System.Web.HttpContext.Current.Items["ModuleRoleBitmask"] = userContext.ModuleRoleBitmask;
                        System.Web.HttpContext.Current.Items["ConnectionString"] = Utility.DataAccess.ConnectionString;
                    }
                }
            }
            catch (Exception ex)
            {
                Tracer.Trace(string.Format("Application_PreRequestHandlerExecute: {0}", ER.GetExceptionInfo(ex, false)));
            }
        }


        /// <summary>
        /// Record the following information pertaining to the about-to-be-completed request in the Activity table:
        /// User ID
        /// Browser name and version
        /// Client platform
        /// Source URL (originator of the request)
        /// Destination URL (target of the request)
        /// Current module name
        /// Search criteria (both raw and cooked - the cooked one contains user-readable names and values)
        /// </summary>
        /// <param name="sender">Source of the event</param>
        /// <param name="e">Argument associated with the event</param>
        protected void Application_PostRequestHandlerExecute(Object sender, EventArgs e)
        {
            try
            {
                Policy.ICachePolicy icachePolicy = (Policy.ICachePolicy)Session[Policy.Names.PageCachePolicyKey];
                if (icachePolicy != null)
                {
                    string cmodule = icachePolicy.GetCachedObject(SearchContext.SearchContext.CurrentModuleKey) as string;
                    if (cmodule != null)
                    {
                        if (Session["Modules"] == null)
                        {
                            Hashtable hst = new Hashtable();
                            try
                            {
                                hst.Add(cmodule, "1");
                                Session["Modules"] = hst;
                            }
                            catch {}
                        }
                        else
                        {
                            try
                            {
                                Hashtable hst = (Hashtable)Session["Modules"];
                                hst.Add(cmodule, "1");
                                Session["Modules"] = hst;
                            }
                            catch {}
                        }
                    }
                }

                if (Convert.ToBoolean(Application[TrackActivityKey]))
                {
                    Policy.ICachePolicy cachePolicy = (Policy.ICachePolicy)Session[Policy.Names.PageCachePolicyKey];
                    if (cachePolicy != null)
                    {
                        UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                        if (userContext != null)
                        {
                            HttpBrowserCapabilities bc = Request.Browser;

                            SqlParameter[] args = DataAccess.BuildSqlParameterArray(
                                "@sessionID", SqlDbType.VarChar, Session.SessionID,
                                "@domainUserID", SqlDbType.Int, userContext.DomainUserId,
                                "@browser", SqlDbType.VarChar, string.Format("{0} {1}", bc.Browser, bc.Version),
                                "@platform", SqlDbType.VarChar, bc.Platform,
                                "@userHost", SqlDbType.VarChar, Request.UserHostAddress,
                                "@sourceURL", SqlDbType.VarChar, Request.UrlReferrer.ToString(),
                                "@destinationURL", SqlDbType.VarChar, Request.Url.ToString());

                            string module = cachePolicy.GetCachedObject(SearchContext.SearchContext.CurrentModuleKey) as string;
                            if (module != null)
                                DataAccess.AppendToSqlParameterArray(ref args, "@module", SqlDbType.VarChar, module);

                            CommonSearchContext searchContext = cachePolicy.GetCachedObject(CommonSearchContext.CacheKey) as CommonSearchContext;
                            if (searchContext != null)
                            {
                                SearchCriteria searchCriteria = searchContext.GetSearchCriteria(Request.Url.ToString());
                                DataAccess.AppendToSqlParameterArray(ref args,
                                    "@rawSearchCriteria", SqlDbType.VarChar, searchCriteria.ToString(),
                                    "@cookedSearchCriteria", SqlDbType.VarChar, searchCriteria.ToString(","));
                            }

                            DataAccess.ExecuteNonQuery(DataAccess.ConnectionString, "UpdateActivity", args);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Tracer.Trace(string.Format("Application_PostRequestHandlerExecute: {0}", ER.GetExceptionInfo(ex, false)));
            }
        }

        /// <summary>
        /// Transfer to the common error page which will display a user-friendly message. This is a configurable action.
        /// </summary>
        /// <param name="sender">Event source</param>
        /// <param name="e">Argument associated with the event</param>
        protected void Application_Error(Object sender, EventArgs e)
        {
            Exception ex = Server.GetLastError();
            EventLog.WriteEntry("Insight", Utility.ExceptionReport.GetExceptionInfo(ex, true), EventLogEntryType.Error);


            if (Session == null)
            {
                //session timeout
                Response.Redirect(Utility.Settings.GetKeyValue("Header.Logout", "") + "?message=" + ex.Message, false);

            }
            else if (Session[UserContext.CacheKey] == null)
            {
                //session timeout
                Response.Redirect(Utility.Settings.GetKeyValue("Header.Logout", "") + "?message=" + "Your session has timed out due to an extended period of inactivity.", false);

            }
            else
            {
                //other error
                Response.Redirect(Utility.Settings.GetKeyValue("Header.Logout", "") + "?message=" + ex.Message, false);

            }
        }

        /// <summary>
        /// Event raised when a user's session ends. Remove all objects cached in the session.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Session_End(Object sender, EventArgs e)
        {
            try
            {
                Policy.ICachePolicy cachePolicy = (Policy.ICachePolicy)Session[Policy.Names.PageCachePolicyKey];
                if (cachePolicy != null)
                {
                    UserContext userContext = cachePolicy.GetCachedObject(UserContext.CacheKey) as UserContext;
                    if (userContext != null)
                    {
                        Hashtable hst = (Hashtable)Session["Modules"];
                        if (hst != null)
                        {
                            StringBuilder modulenames = new StringBuilder();
                            modulenames.Append("<modules>");
                            foreach (DictionaryEntry entry in hst)
                            {
                                modulenames.Append("<module MName=\"" + entry.Key + "\"/>");
                            }
                            modulenames.Append("</modules>");

                            SqlParameter[] args = DataAccess.BuildSqlParameterArray(
                                                "@modules", SqlDbType.VarChar, modulenames.ToString(),
                                                "@userName", SqlDbType.VarChar, userContext.Username);
                            DataAccess.ExecuteNonQuery(DataAccess.ConnectionString, "usp_InsertModuleHit", args);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Tracer.Trace(string.Format("Session_End: {0}", ER.GetExceptionInfo(ex, false)));
            }
            
            if (Session[Policy.Names.CachePolicyKey] != null)
                ((Policy.ICachePolicy)Session[Policy.Names.CachePolicyKey]).Purge(null);
            if (Session[Policy.Names.PageCachePolicyKey] != null)
                ((Policy.ICachePolicy)Session[Policy.Names.PageCachePolicyKey]).Purge(null);
        }

        /// <summary>
        /// Event raised when IIS is restarted gracefully
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Application_End(Object sender, EventArgs e)
        {
            Application.Remove(Policy.Names.ApplicationCachePolicyKey);
        }
        #endregion

        #region Web Form Designer generated code
        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InitializeComponent()
        {
        }
        #endregion
    }
}

// --- EOF ---
